#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <sstream>

using namespace std;

const string HttpSep = "\r\n";
const string homepage = "index.html";
const string wwwroot = "./wwwroot";

class HttpRequest
{
public:
    HttpRequest() : _req_blank(HttpSep), _path(wwwroot)
    {
    }
    ~HttpRequest() {}

    bool GetLine(string &request, string *line)//获取每一行的内容，每一行间隔的标志是"\r\n"
    {
        auto pos = request.find(HttpSep);
        if (pos == string::npos)
        {
            return false;
        }
        *line = request.substr(0, pos);         //将获取的一行放到line存储，没有获取"\r\n"
        request.erase(0, pos + HttpSep.size()); //删除行和分隔符
        return true;
    }
    bool Deserialize(string &request)
    {
        string line;
        bool ok = GetLine(request, &line);
        if (!ok)
            return false;
        _req_line = line; // 将第一行信息保存到_req_line中
        // 一直解析
        while (true)
        {
            bool ok = GetLine(request, &line);
            if (ok && line.empty())
            {
                _req_content = request; // http请求除了头部还有内容，所以把剩下的内容保存起来
                break;
            }
            else if (ok && !line.empty())
            {
                _req_header.push_back(line); // 将头部每一行信息保存到vector中
            }
            else
            {
                break;
            }
        }
        return true;
    }
    void Debug()
    {
        cout << "req_line(状态行)" << _req_line << endl;
        for (auto &line : _req_header)
        {
            cout << "--->" << line << endl;
        }
        cout << "_req_blank :" << _req_blank << endl;
        cout << "_req_content   :" << _req_content << endl;

        cout << "method:" << _method << endl;
        cout << "url:" << _url << endl;
        cout << "http_version:" << _http_version << endl;
    }
    string GetFileContentHelper(const string& path)//根据解析到的路径获取文件内容
    {
        ifstream in(path, ios::in | ios::binary);
        if (!in.is_open())
            return "";

        in.seekg(0, in.end);//将文件指针移动到文件的末尾
        int filesize = in.tellg();//获取文件大小
        in.seekg(0, in.beg);//将文件指针移动到文件的开头

        string content;
        content.resize(filesize);//分配空间
        in.read((char *)content.c_str(), filesize);//读取文件内容

        // vector<char> content(filesize);
        // in.read(content.data(), filesize);

        in.close();
        return content;
    }

    void ParseReqLine()//解析状态行
    {
        stringstream ss(_req_line);
        ss >> _method >> _url >> _http_version;

        // 处理url
        // 如果访问的是根目录，就把首页给他
        if (_url == "/")
        {
            _path += _url + homepage;// ./wwwroot+/+"index.html";
        }
        else
        {
            _path += _url;// ./wwwroot+_url;
        }
    }
    void ParseSuffix()//解析后缀
    {
        // 处理后缀
        auto pos = _path.rfind(".");//整个路径从后往前找"."，找到最后一个"."的位置
        if (pos == string::npos)
            _suffix = ".html";//没找到"."，就默认是".html"
        else
            _suffix = _path.substr(pos);
    }
    void Parse()
    {
        // 1。分析请求，解析第一行
        ParseReqLine();
        // 2.wwwroot
        ParseSuffix();
    }
    string GetFileContent()
    {
        return GetFileContentHelper(_path);
    }
    string Get_404()
    {
        return GetFileContentHelper("./wwwroot/404.html");
    }
    string GetUrl()
    {
        return _url;
    }
    string GetPath()
    {
        return _path;
    }
    string GetSuffix()
    {
        return _suffix;
    }
    string GetVersion()
    {
        return _http_version;
    }
private:
    string _req_line;// 状态行
    vector<string> _req_header;// 头部信息
    string _req_blank;// 空行
    string _req_content;// 请求内容

    // 解析之后的内容
    //状态行的内容
    string _method;// 请求方法
    string _url;// 请求路径
    string _http_version;// http版本

    string _path;// 指定的请求路径（在用户的_url中指定一个路径，防止用户访问服务器的任意文件）
    string _suffix; // 请求资源后缀
};

const string BlankSep=" ";
const string LineSep="\r\n";

class HttpResponse
{
public:
    HttpResponse():_http_version("HTTP/1.0"),_status_code(200),_status_desc("OK")//默认状态码是200
    ,_resp_blank(LineSep)
    {
    }
    void SetCode(int code)
    {
        _status_code=code;
    }
    void SetVersion(const string& version)
    {
        _http_version=version;
    }
    void SetDesc(const string& desc)
    {
        _status_desc=desc;
    }
    void MakeStatusLine()
    {
        _status_line=_http_version+BlankSep+to_string(_status_code)+BlankSep+_status_desc+LineSep;
    }
    void AddHeader(const string& header)
    {
        _resp_header.push_back(header);
    }
    void AddContent(const string& content)
    {
        _resp_content=content;
    }
    
    string Serialize()//序列化
    {
        string response_str=_status_line;
        for(auto &header:_resp_header)
        {
            response_str+=header+LineSep;
        }
        response_str+=_resp_blank;//添加空行
        response_str+=_resp_content;///添加内容

        return response_str;//返回序列化后的字符串
    }

    ~HttpResponse()
    {
    }

private:
    string _status_line;// 状态行
    vector<string> _resp_header;// 头部信息
    string _resp_blank;// 空行
    string _resp_content;// 响应内容

    //http版本 状态码 状态码描述
    string _http_version;// http版本
    int _status_code;// 状态码
    string _status_desc;// 状态码描述

};